# 代码参考自https://github.com/kwiersma/flask-celery-sqlalchemy/blob/master/app/celeryapp/__init__.py，为了辅助celery和flask的底层操作交互融为一体，解决执行celery任务outside of app context问题

import logging
import sys

from celery import Celery
from celery.signals import after_setup_logger
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker,scoped_session

CELERY_TASK_LIST=['app.tasks',]
db_session=None
celery=None

def create_celery_app(_app=None):
    from app import celery_config
    from app import db
    celery=Celery(_app.import_name)
    celery.config_from_object(celery_config)
    celery.autodiscover_tasks(CELERY_TASK_LIST)

    TaskBase=celery.Task

    class ContextTask(TaskBase):
        abstract=True
        def __call__(self,*args,**kwargs):
            if not celery.conf['task_always_eager']:
                with _app.app_context():
                    return TaskBase.__call__(self,*args,**kwargs)
            else:
                db.session=db_session
                return TaskBase.__call__(self,*args,**kwargs)
            
        def after_return(self,status,retval,task_id,args,kwargs,einfo):
            if _app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']:
                if not isinstance(retval,Exception):
                    db.session.commit()
            if not celery.conf['task_always_eager']:
                db.session.remove()
            
    celery.Task=ContextTask
    return celery

@after_setup_logger.connect
def setup_loggers(logger,*args,**kwargs):
    logger.addHandler(logging.StreamHandler(sys.stdout))